package com.shenghua.service.impl;

import com.shenghua.dao.bean.RoleBean;
import com.shenghua.dao.bean.UserBean;
import com.shenghua.dao.mapper.RolesMapper;
import com.shenghua.dao.mapper.UserMapper;
import com.shenghua.dao.mapperX.RoleLimitMapperX;
import com.shenghua.dao.mapperX.UserMapperX;
import com.shenghua.dao.model.RoleLimitX;
import com.shenghua.dao.model.Roles;
import com.shenghua.dao.model.User;
import com.shenghua.dao.model.UserExample;
import com.shenghua.service.LoginService;
import com.shenghua.utils.ListUtils;
import com.shenghua.utils.RedisUtils;
import com.shenghua.utils.StringUtils;
import com.shenghua.utils.beans.Constants;
import com.shenghua.utils.constants.UserStatus;
import org.apache.shiro.authc.CredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author: yzr
 * @date: 2020/2/22
 */
@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserMapperX userMapperX;
    @Autowired
    private RolesMapper rolesMapper;
    @Resource
    private RoleLimitMapperX roleLimitMapperX;
    @Resource
    private RedisUtils redisUtils;
    @Value(value = "${LoginRedisLock}")
    private boolean LoginRedisLock;//用户登录开启redis锁

    @Override
    public UserBean getUserByName(String username) {
        UserExample userExample = new UserExample();
        UserExample.Criteria criteria = userExample.createCriteria();
        criteria.andLinkmanEqualTo(username);
        userExample.or(criteria);

        UserExample.Criteria criteria1 = userExample.createCriteria();
        criteria1.andPhoneEqualTo(username);
        userExample.or(criteria1);
        List<User> userList = userMapper.selectByExample(userExample);
        if(ListUtils.isEmpty(userList)) { // 用户名不存在
            throw new CredentialsException();
        }
        User user = userList.get(0);
        if(StringUtils.isBlank(user.getStatus()) || //账号状态未知
                UserStatus.STOPED.getVal().equalsIgnoreCase(user.getStatus()) || //账号已停用
                UserStatus.FORBIDDEN.getVal().equalsIgnoreCase(user.getStatus()) || //账号已禁用
                UserStatus.FROZEN.getVal().equalsIgnoreCase(user.getStatus())) {//账号已冻结
            throw new LockedAccountException();
        }
        // 禁止多次登录
        if(LoginRedisLock && !redisUtils.lock(user.getLinkman())) {//账号加锁失败
            throw new LockedAccountException();
        }

        return shiroUser(user);
    }

    @Override
    public UserBean shiroUser(User user) {
        UserBean userBean = new UserBean();
        userBean.setUser(user);

        if(StringUtils.isBlank(user.getRoleId())) {
            throw new LockedAccountException();
        }
        String roleId = user.getRoleId().toString();
        RoleBean roleBean = null;

        Roles roles = rolesMapper.selectByPrimaryKey(Integer.parseInt(roleId));
        if(StringUtils.isNotBlank(roles.getSign()) && Constants.ROLES_SUPER_ADMIN.equals(roles.getSign())) {
            List<RoleLimitX> roleLimitXList = roleLimitMapperX.queryAllLimit_normal();
            if(ListUtils.isNotEmpty(roleLimitXList)) {
                roleBean = new RoleBean(roles, roleLimitXList);
            }
        } else {
            List<RoleLimitX> roleLimitXList = roleLimitMapperX.queryMenuLimitByRoleId_normal(roleId);
            if(ListUtils.isNotEmpty(roleLimitXList)) {
                roleBean = new RoleBean(roles, roleLimitXList);
            }
        }
        Set<RoleBean> roleBeanSet = new HashSet<>();
        roleBeanSet.add(roleBean);
        userBean.setRoleBeanSet(roleBeanSet);
        return userBean;
    }

    /**
     * 获取shiro的认证信息
     *
     * @param userBean
     * @param user
     * @param realmName
     */
    @Override
    public SimpleAuthenticationInfo getAuthenticationInfo(UserBean userBean, User user, String realmName) {
        String credentials = user.getPassword();

        // 密码加盐处理
        String source = user.getSalt();
        ByteSource credentialsSalt = new Md5Hash(source);
        return new SimpleAuthenticationInfo(userBean, credentials, credentialsSalt, realmName);
    }

}
